package com.companyname.projecttemplate.ws;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;

import com.base.core.head.ao.WsMessageAO;
import com.base.core.mvc.ws.WsState;
import com.companyname.projecttemplate.mapping.ApiMapping;
import com.gitee.magic.context.ConverterEditorUtils;
import com.gitee.magic.core.json.JsonObject;
import com.gitee.magic.core.utils.reflect.TypeReference;

import lombok.extern.slf4j.Slf4j;

/**
 * 
 * @author start
 *
 */
@Slf4j
@Component
public class AppWebSocketHandler extends AbstractWebSocketHandler {

	public final static String WS_ONLINE="online";
	public final static String WEBSOCKET_TOKEN="WEBSOCKET_TOKEN";
	
	@Value("${mq.ws.service.channel}")
	private String webSocketServiceChannel;

	public final static Map<String, WebSocketSession> SESSIONPOOL = new ConcurrentHashMap<>(100);

	@Autowired
	private ApiMapping apiMapping;
	@Autowired
	private StringRedisTemplate stringRedisTemplate;

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
    	Long userId=Long.parseLong(String.valueOf(session.getAttributes().get(WEBSOCKET_TOKEN)));
    	apiMapping.wsConnection(userId);
    	setHeartbeat(session,true);
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
    	log.info("handleTextMessage {}",message.getPayload());
    	if(WS_ONLINE.equals(message.getPayload())) {
	    	setHeartbeat(session,false);
    	}else {
			//TODO：线上环境建议使用MQ
    		WsMessageAO<String> ao=ConverterEditorUtils.restoreObject(
    				WsMessageAO.class, new JsonObject(message.getPayload()),new TypeReference<WsMessageAO<String>>() {});
    		ao.setUserId(Long.parseLong(String.valueOf(session.getAttributes().get(WEBSOCKET_TOKEN))));
    		apiMapping.wsHandleMessage(ao);
    	}
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
    	log.info("afterConnectionClosed {}",session.getAttributes());
    	String userId=String.valueOf(session.getAttributes().get(WEBSOCKET_TOKEN));
        String userKey=WsState.getWebSocketUserId(userId);
        if(stringRedisTemplate.hasKey(userKey)) {
        	stringRedisTemplate.delete(userKey);
        }
        SESSIONPOOL.remove(userId);
    }
    
    /**
     * 设置心跳自动过期
     * @param session
     */
    public void setHeartbeat(WebSocketSession session,Boolean isInit) {
    	log.info("setHeartbeat {}",session.getAttributes());
    	String userId=String.valueOf(session.getAttributes().get(WEBSOCKET_TOKEN));
    	if(isInit) {
    		if(SESSIONPOOL.containsKey(userId)) {
    			WebSocketSession sess=SESSIONPOOL.get(userId);
    			try {
					sess.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
    		}
    		SESSIONPOOL.put(userId, session);
    	}
    	String userKey=WsState.getWebSocketUserId(userId);
    	stringRedisTemplate.opsForValue().set(userKey, webSocketServiceChannel,1,TimeUnit.MINUTES);
    }
    
}
